Helper.using('py.Figures', function (ns) {

    //DaoLA
    ns.AngleMagnitude = function (params) {
        ns.LinearObject.call(this, params);
        this.setType('AngleMagnitude');

        params = Helper.extend({
            radian:0
        }, params);

        this.getRadian = function(){
            return params.radian;
        }

        this.getDegree = function(){
            return this.toDegree(this.getRadian());
        }

        this.toDegree = function(rad){
            return rad * 180 / Math.PI;
        }

        this.toRadian = function(deg){
            return deg * Math.PI / 180;
        }
    };

    ns.AngleMagnitude.fromDegree = function (deg) {
        return new ns.AngleMagnitude({radian: deg * Math.PI / 180});
    };

    ns.AngleMagnitude.fromRadian = function(rad){
        return new ns.AngleMagnitude({radian:rad});
    };

    ns.Angle = function (params) {
        ns.LinearObject.call(this, params);
        this.setType('Angle');

       /* this.visual(new Kinetic.Angle({
            stroke:"blue",
            strokeWidth:5,
            lineCap:"round",
            lineJoin:"round"
        }));*/

        this.getMagnitude = Helper.abstractMethod();

    };

    // Angle sub-class

    /* Finding angle between 3 points
     * Use cosin theorem : cosB = (a^2 + c^2 - b^2)/ (2*a*c)
     */
    ns.Angle3Point = function (params) {
        ns.Angle.call(this, params);
        this.setType('Angle3Point');

        if (!params.points || params.points.length != 3) {
            throw new Error('Parameter is invalid !!! Must contains array of three points');
            return;
        }

        /*params = Helper.extend({
         lines:null
         }, params);*/

        var pA, pB, pC;
        var a, b, c; // square distance
        var cosA, cosB, cosC;

        var initialize = function () {
            pA = params.points[0];
            pB = params.points[1];
            pC = params.points[2];

            a = ns.Point.distanceR(pB, pC);
            b = ns.Point.distanceR(pC, pA);
            c = ns.Point.distanceR(pA, pB);

            cosA = (b + c - a) / (2 * Math.sqrt(b * c));
            cosB = (a + c - b) / (2 * Math.sqrt(a * c));
            cosC = (a + b - c) / (2 * Math.sqrt(a * b));

        };

        initialize();

        this.getAngleA = function () {
            return Math.acos(cosA) * 180 / Math.PI;
        };
        this.getAngleB = function () {
            return Math.acos(cosB) * 180 / Math.PI;
        };

        this.getAngleC = function () {
            return Math.acos(cosC) * 180 / Math.PI;
        };

        this.setPoints = function (points) {
            params.points = points;
            initialize();
        };

    };

    //DaoLA
//    ns.AngleWithOx = function (params) {
//        ns.Angle.call(this, params);
//        this.setType('AngleWithOx');
//
//        var empty = new ns.Vector();
//
//        params = Helper.extend({
//            vector:empty
//        }, params);
//
//        this.getMagnitude = function () {
//            var y = params.vector.getY(),
//                x = params.vector.getX();
//            return new ns.AngleMagnitude({radian:Math.atan(y / x)});
//        }
//    };

    //DaoLA
    ns.Angle2Line = function(params){
        ns.Angle.call(this, params);
        this.setType('Angle2Line');

        params = Helper.extend({
            lines: []
        }, params);

        this.getLineA = function () {
            return params.lines[0];
        };

        this.getLineB = function () {
            return params.lines[1];
        };

        this.getMagnitude = function(){
            var y2 = this.getLineB().getDirectionVector().getY(),
                x2 = this.getLineB().getDirectionVector().getX(),
                y1 = this.getLineA().getDirectionVector().getY(),
                x1 = this.getLineA().getDirectionVector().getX();
            var rad = Math.atan(y2/x2) - Math.atan(y1/x1);
            return new ns.AngleMagnitude({radian:rad});
        }
    }

    //DaoLA
    ns.AngleWithMagnitude = function(params){
        ns.Angle.call(this, params);
        this.setType('AngleWithMagnitude');

        params = Helper.extend({
            lines: []
        }, params);
    }
});